package com.swcw.platform.utils;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import com.swcw.platform.constants.OwnConstant;
import com.swcw.platform.utils.bean.RedisBean;

import net.sf.json.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * redis数据库链接工具
 * 
 * @see:
 * @Company:江苏鸿信系统集成有限公司微信开发组
 * @author 杨坚
 * @Time 2016年11月24日
 * @version 1.0v
 */
public final class RedisAPI {

	// 可用连接实例的最大数目，默认值为8；
	private static int MAX_TOTAL = 1024;

	// 控制一个jedisPool最多有多少个状态为idle(空闲的)的jedis实例，默认值也是8。
	private static int MAX_IDLE = 200;

	// 等待可用连接的最大时间，单位毫秒，默认值为-1，表示永不超时。如果超过等待时间，则直接抛出JedisConnectionException；
	private static int MAX_WAIT = 10000;

	private static int TIMEOUT = 10000;
	// 获取连接是否校验可用
	private static boolean TEST_ON_BORROW = true;
	// 主1
	private static JedisPool jedisPoolMasterOne = null;
	// 主2
	private static JedisPool jedisPoolMasterTwo = null;

	// 从1
	private static JedisPool jedisPoolFollowOne = null;
	// 从2
	private static JedisPool jedisPoolFollowTwo = null;
	// 从3
	private static JedisPool jedisPoolFollowThree = null;
	// 从4
	private static JedisPool jedisPoolFollowFour = null;
	// 从数据库数量
	private static int FOLLOW = 0;
	// 主数据库数量
	private static int MASTER = 0;

	/**
	 * 初始化Redis连接池
	 */
	static {
		// true开启 false不开启
		if (OwnConstant.REDIS_INIT_SWITCH) {
			// 从数量
			FOLLOW = OwnConstant.followRedisList.size();
			// 主数量
			MASTER = OwnConstant.masterRedisList.size();
			try {
				// 获取主初始化数据
				List<RedisBean> masterRedisList = OwnConstant.masterRedisList;
				for (int i = 0; i < masterRedisList.size(); i++) {
					System.out.println("=====主服务====>" + JSONObject.fromObject(masterRedisList.get(i)));
					// IP
					String ip = masterRedisList.get(i).getRedisIp();
					// 端口
					Integer port = masterRedisList.get(i).getRedisPort();
					// 鉴权
					String auth = masterRedisList.get(i).getRedisAuth();
					// 数据库列表
					Integer database = masterRedisList.get(i).getRedisDataBase();
					switch (i) {
					case 0:
						JedisPoolConfig configMasterOne = new JedisPoolConfig();
						configMasterOne.setMaxTotal(MAX_TOTAL);
						configMasterOne.setMaxIdle(MAX_IDLE);
						configMasterOne.setMaxWaitMillis(MAX_WAIT);
						configMasterOne.setTestOnBorrow(TEST_ON_BORROW);
						jedisPoolMasterOne = new JedisPool(configMasterOne, ip, port, TIMEOUT, auth,
								database == null ? 0 : database);
						break;
					case 1:
						JedisPoolConfig configMasterTwo = new JedisPoolConfig();
						configMasterTwo.setMaxTotal(MAX_TOTAL);
						configMasterTwo.setMaxIdle(MAX_IDLE);
						configMasterTwo.setMaxWaitMillis(MAX_WAIT);
						configMasterTwo.setTestOnBorrow(TEST_ON_BORROW);
						jedisPoolMasterTwo = new JedisPool(configMasterTwo, ip, port, TIMEOUT, auth,
								database == null ? 0 : database);
						break;

					}
				}
				// 获取从初始化数据
				List<RedisBean> followRedisList = OwnConstant.followRedisList;
				for (int i = 0; i < followRedisList.size(); i++) {
					System.out.println("=====从服务====>" + JSONObject.fromObject(followRedisList.get(i)));
					// IP
					String ip = followRedisList.get(i).getRedisIp();
					// 端口
					Integer port = followRedisList.get(i).getRedisPort();
					// 鉴权
					String auth = followRedisList.get(i).getRedisAuth();
					// 数据库列表
					Integer database = followRedisList.get(i).getRedisDataBase();
					switch (i) {
					case 0:
						JedisPoolConfig configFollowOne = new JedisPoolConfig();
						configFollowOne.setMaxTotal(MAX_TOTAL);
						configFollowOne.setMaxIdle(MAX_IDLE);
						configFollowOne.setMaxWaitMillis(MAX_WAIT);
						configFollowOne.setTestOnBorrow(TEST_ON_BORROW);
						jedisPoolFollowOne = new JedisPool(configFollowOne, ip, port, TIMEOUT, auth,
								database == null ? 0 : database);
						break;
					case 1:
						JedisPoolConfig configFollowTwo = new JedisPoolConfig();
						configFollowTwo.setMaxTotal(MAX_TOTAL);
						configFollowTwo.setMaxIdle(MAX_IDLE);
						configFollowTwo.setMaxWaitMillis(MAX_WAIT);
						configFollowTwo.setTestOnBorrow(TEST_ON_BORROW);
						jedisPoolFollowTwo = new JedisPool(configFollowTwo, ip, port, TIMEOUT, auth,
								database == null ? 0 : database);
						break;
					case 2:
						JedisPoolConfig configFollowThree = new JedisPoolConfig();
						configFollowThree.setMaxTotal(MAX_TOTAL);
						configFollowThree.setMaxIdle(MAX_IDLE);
						configFollowThree.setMaxWaitMillis(MAX_WAIT);
						configFollowThree.setTestOnBorrow(TEST_ON_BORROW);
						jedisPoolFollowThree = new JedisPool(configFollowThree, ip, port, TIMEOUT, auth,
								database == null ? 0 : database);
						break;
					case 3:
						JedisPoolConfig configFollowFour = new JedisPoolConfig();
						configFollowFour.setMaxTotal(MAX_TOTAL);
						configFollowFour.setMaxIdle(MAX_IDLE);
						configFollowFour.setMaxWaitMillis(MAX_WAIT);
						configFollowFour.setTestOnBorrow(TEST_ON_BORROW);
						jedisPoolFollowFour = new JedisPool(configFollowFour, ip, port, TIMEOUT, auth,
								database == null ? 0 : database);
						break;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 选择主数据库连接池 使用完立即将连接释放到连接池(写操作)
	 * 
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static Jedis masterChooseConnect(String key) {
		Jedis jedisResource = null;
		if (MASTER <= 1) {
			return jedisPoolMasterOne.getResource();
		} else {
			if (StringUtils.isNotEmpty(key)) {
				// 获取ASCII码
				char[] chars = key.toCharArray();
				int ascll = (int) chars[0];
				switch (ascll <= 90 ? 0 : 1) {
				case 0:
					jedisResource = jedisPoolMasterOne.getResource();
					break;
				case 1:
					jedisResource = jedisPoolMasterTwo.getResource();
					break;
				}
			}
		}
		return jedisResource;
	}

	/**
	 * 选择从数据库连接池 使用完立即将连接释放到连接池(读操作)
	 * 
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static Jedis followChooseConnect() {
		Jedis jedisResource = null;
		if (FOLLOW <= 1) {
			return jedisPoolFollowOne.getResource();
		} else {
			Random ra = new Random();
			switch (ra.nextInt(FOLLOW)) {
			case 0:
				jedisResource = jedisPoolFollowOne.getResource();
				break;
			case 1:
				jedisResource = jedisPoolFollowTwo.getResource();
				break;
			case 2:
				jedisResource = jedisPoolFollowThree.getResource();
				break;
			case 3:
				jedisResource = jedisPoolFollowFour.getResource();
				break;
			}
		}
		return jedisResource;
	}

	/**
	 * 字符串形式添加
	 * 
	 * @param key
	 *            键
	 * @param value
	 *            值
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月17日
	 * @version 1.0v
	 */
	public static String setKeyToValueStr(String key, String value) {
		Jedis jedis = null;
		try {
			jedis = masterChooseConnect(null);
			return jedis.set(key, value);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return "0";
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 二进制添加
	 * 
	 * @param key
	 * @param values
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static String setKeyToValueBytes(String key, Object values) {
		Jedis jedis = null;
		try {
			jedis = masterChooseConnect(null);
			return jedis.set(key.getBytes(), SerializationUtil.serialize(values));
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return "0";
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 根据key删除信息
	 * 
	 * @param key
	 *            键
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月17日
	 * @version 1.0v
	 */
	public static Long delKeyStr(String key) {
		Jedis jedis = null;
		try {
			jedis = masterChooseConnect(null);
			return jedis.del(key.getBytes());
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return (long) 0;
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 根据key删除信息
	 * 
	 * @param key
	 *            键
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月17日
	 * @version 1.0v
	 */
	public static Long delKeyBytes(String key) {
		Jedis jedis = null;
		try {
			jedis = masterChooseConnect(null);
			return jedis.del(key.getBytes());
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return (long) 0;
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 判断是否存在key
	 * 
	 * @author 杨坚
	 * @Time 2016年10月2日
	 * @param key
	 *            键
	 * @return
	 */
	public static boolean existsBytes(String key) {
		Jedis jedis = null;
		try {
			jedis = followChooseConnect();
			return jedis.exists(key.getBytes());
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return false;
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 判断是否存在key
	 * 
	 * @author 杨坚
	 * @Time 2016年10月2日
	 * @param key
	 *            键
	 * @return
	 */
	public static Object existsBytesToValue(String key) {
		Jedis jedis = null;
		byte[] value = null;
		try {
			jedis = followChooseConnect();
			if (jedis.exists(key.getBytes())) {
				value = jedis.get(key.getBytes());
				return SerializationUtil.deserialize(value);
			}
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return null;
		} finally {
			closeJedis(jedis);
		}
		return null;
	}

	/**
	 * 判断是否存在key String
	 * 
	 * @author 杨坚
	 * @Time 2016年10月2日
	 * @param key
	 *            键
	 * @return
	 */
	public static boolean existsStr(String key) {
		Jedis jedis = null;
		try {
			jedis = followChooseConnect();
			return jedis.exists(key);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return false;
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 获取数据信息Object
	 * 
	 * @param key
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static Object getValue(String key) {
		Jedis jedis = null;
		byte[] value = null;
		try {
			jedis = followChooseConnect();
			value = jedis.get(key.getBytes());
			return SerializationUtil.deserialize(value);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
		} finally {
			closeJedis(jedis);
		}
		return null;
	}

	/**
	 * 以Map形式添加数据
	 * 
	 * @param key
	 * @param map
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static String setMap(String key, Map<String, String> map) {
		Jedis jedis = null;
		try {
			jedis = masterChooseConnect(null);
			return jedis.hmset(key, map);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return "0";
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 添加数据并设置时间
	 * 
	 * @param key
	 * @param time
	 *            过期时间
	 * @param value
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static String setStrTime(String key, int time, String value) {
		Jedis jedis = null;
		try {
			jedis = masterChooseConnect(null);
			return jedis.setex(key, time, value);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return "0";
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 以二进制来添加数据并设置时间
	 * 
	 * @param key
	 * @param time
	 *            过期时间
	 * @param value
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static String setByteTime(byte[] key, int time, byte[] value) {
		Jedis jedis = null;
		try {
			jedis = masterChooseConnect(null);
			return jedis.setex(key, time, value);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return "0";
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 获取map形式长度
	 * 
	 * @param key
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static long getMapLen(String key) {
		Jedis jedis = null;
		try {
			jedis = followChooseConnect();
			return jedis.hlen(key);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return 0;
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 获取map形式的键
	 * 
	 * @param key
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static Set<String> getMapKey(String key) {
		Jedis jedis = null;
		try {
			jedis = followChooseConnect();
			return jedis.hkeys(key);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return null;
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 获取map形式的值
	 * 
	 * @param key
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static List<String> getMapValue(String key) {
		Jedis jedis = null;
		try {
			jedis = followChooseConnect();
			return jedis.hvals(key);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return null;
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 删除map形式中的键值对
	 * 
	 * @param key
	 *            数据库中的key
	 * @param paramKey
	 *            map中的key
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static Long getMapValue(String key, String paramKey) {
		Jedis jedis = null;
		try {
			jedis = followChooseConnect();
			return jedis.hdel(key, paramKey);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
			return null;
		} finally {
			closeJedis(jedis);
		}
	}

	/**
	 * 根据键获取信息
	 * 
	 * @param key
	 * @return
	 * @author 杨坚
	 * @Time 2016年11月17日
	 * @version 1.0v
	 */
	public static String getKeyStr(String key) {
		Jedis jedis = null;
		String value = null;
		try {
			jedis = followChooseConnect();
			value = jedis.get(key);
		} catch (Exception e) {
			closeJedis(jedis);
			e.printStackTrace();
		} finally {
			closeJedis(jedis);
		}
		return value;
	}

	/**
	 * 释放jedis资源
	 * 
	 * @param jedis
	 * @author 杨坚
	 * @Time 2016年11月24日
	 * @version 1.0v
	 */
	public static void closeJedis(final Jedis jedis) {
		if (jedis != null) {
			jedis.close();
		}
	}

}